from typing import Any, Optional, Tuple, Union, Dict, List

from django.core.handlers.wsgi import WSGIRequest
from django.contrib.auth import authenticate, login
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.utils import timezone
from django.urls import reverse

from . import forms
from . import models


class UsersUtils:

    def get_authorization_context_with_error(
        self,
        form: forms.UserLoginForm,
        errors: Union[List[str], str]
    ) -> Dict[str, Union[forms.UserLoginForm, List[str]]]:
        """ Получаем контекст для авторизации с ошибкой """

        if type(errors) == str:
            errors = [errors]

        context = {
            'form': form,
            'list_of_errors': errors
        }
        return context


    def try_authorize_user(
        self,
        request: WSGIRequest,
        user: Optional[models.CustomUser],
        form: forms.UserLoginForm
    ) -> Tuple[bool, Union[HttpResponse, models.CustomUser]]:
        """ Проверяем введенные данные """

        if user is not None:
            response = (True, user)
        else:
            context = self.get_authorization_context_with_error(
                form,
                errors='Проверьте корректность введнного логина или пароля. \
                        Узнайте, активирован ли Ваш аккаунт.'
            )
            response = (
                False,
                render(request, 'registration/login.html', context)
            )
        return response


    def authorize_user(
        self,
        request: WSGIRequest,
        user: models.CustomUser,
        form: forms.UserLoginForm, 
        ) -> Any:
        """ Авторизируем пользователя """

        if not user.license_period >= timezone.now():
            context = self.get_authorization_context_with_error(
                form,
                errors='Срок вашей лицензии истек. Обратитесь к администратору'
            )
            return render(request, 'registration/login.html', context)

        login(request, user)
        return HttpResponseRedirect(reverse('scraper_bitrix:home'))


    def check_entered_data(
        self,
        request: WSGIRequest
    ) -> Tuple[forms.UserLoginForm, Tuple[bool, HttpResponse]]:
        """ Проверяем введенные данные для авторизации """

        form = forms.UserLoginForm(request.POST)

        if form.is_valid():
            cleaned_data = form.cleaned_data
            user = authenticate(
                request=request,
                email=cleaned_data['email'],
                password=cleaned_data['password']
            )
            response = self.try_authorize_user(request, user, form)
        else:
            response = (
                False,
                render(request, 'registration/login.html', {'form': form})
            )

        return (form, response)


    def process_user_authorization(self, request: WSGIRequest) -> Any:
        """ Обрабоатываем авторизацию пользователя """

        form, response = self.check_entered_data(request)
        status, response = response

        if not status:
            return response
        else:
            return self.authorize_user(request, response, form)
